#include "plugin_datablock.h"
#include "datablock_info.h"

#include <QJsonDocument> // 解析 JSON 文档
#include <QJsonObject>   // 操作 JSON 对象
#include <QJsonArray>    // 操作 JSON 数组
#include <QJsonValue>    // 处理 JSON 值
#include <QDebug>        // 调试输出（用于 qDebug）
#include <QString>       // 字符串操作
#include <QSet>
#include <QScroller>
#include <QScrollBar>

/**
 * @brief plugin_datablock::initUi 初始化ui
 */
void plugin_datablock::initUi()
{
    static bool initFlag = true;
    if (initFlag)
    {
        initFlag = false;
        QScroller::grabGesture(plugin_datablock_ui->scrollArea->viewport(), QScroller::TouchGesture); // 允许触摸滑动
    }
}

/**
 * @brief sendMessageToPlugin 接收来自其他任务的信息
 * @param msg
 */
void plugin_datablock::sendMessageToPlugin(const QString &msg)
{
    initUi();
    processJsonCommand(msg);
}

/**
 * @brief plugin_datablock::processJsonCommand 解析json字符串并将内容赋值到m_dataBlockMap
 * @param jsonStr
 */
void plugin_datablock::processJsonCommand(const QString &jsonStr)
{
    // 这里和数据库插件一样，一种是configjson，刷新配置，另一种是data刷新json，只刷新每个块下对应的数据
    QJsonParseError error;
    QJsonDocument doc = QJsonDocument::fromJson(jsonStr.toUtf8(), &error);

    if (error.error != QJsonParseError::NoError)
    {
        emit messageFromPlugin(pluginName(), "JSON analyse failed: " + error.errorString());
        return;
    }

    QJsonObject root = doc.object();

    if (!root.contains("plugin_config") && !root.contains("plugin_data"))
    {
        emit messageFromPlugin(pluginName(), "JSON format error: can not fine plugin_datablock seg");
        return;
    }
    QString root_s = "";
    if (root.contains("plugin_config"))
    {
        root_s = "plugin_config";
    }
    else if (root.contains("plugin_data"))
    {
        root_s = "plugin_data";
    }

    m_dataBlockMap.clear();
    QJsonObject datablock = root[root_s].toObject();
    QJsonArray blocks = datablock["blocks"].toArray();

    // 处理不同的阈值
    QString reTempLimitCD = datablock["tempLimit_cd"].toString(); // 对应普通温度传感器
    if (m_temperatureThreshold != reTempLimitCD.toDouble())
    {
        m_temperatureThreshold = reTempLimitCD.toDouble();
        setTemperatureThreshold(m_temperatureThreshold);
    }

    QString reTempLimitHJ = datablock["tempLimit_hj"].toString(); // 对应柜内温度
    if (m_internalTemperatureThreshold != reTempLimitHJ.toDouble())
    {
        m_internalTemperatureThreshold = reTempLimitHJ.toDouble();
        setInternalTemperatureThreshold(m_internalTemperatureThreshold);
    }

    QString reHumLimit = datablock["humLimit_hj"].toString(); // 对应柜内湿度
    if (m_humidityThreshold != reHumLimit.toDouble())
    {
        m_humidityThreshold = reHumLimit.toDouble();
        setHumidityThreshold(m_humidityThreshold);
    }

    QString reUltrasonicLimit = datablock["dbLImit_cs"].toString(); // 对应超声波
    if (m_ultrasonicThreshold != reUltrasonicLimit.toDouble())
    {
        m_ultrasonicThreshold = reUltrasonicLimit.toDouble();
        setUltrasonicThreshold(m_ultrasonicThreshold);
    }

    QString reTEVLimit = datablock["dbLImit_zt"].toString(); // 对应暂态地电压
    if (m_tevThreshold != reTEVLimit.toDouble())
    {
        m_tevThreshold = reTEVLimit.toDouble();
        setTEVThreshold(m_tevThreshold);
    }

    // 使用QList来保持JSON顺序
    for (const QJsonValue &blockVal : blocks)
    {
        bool isHaveInTemp = false;
        bool isHaveInHum = false;
        bool isHaveInUltrasonic = false; // 超声波标志
        bool isHaveInTEV = false;        // 暂态地电压标志
        QString TempValue = "--";
        QString HumValue = "--";
        QString UltrasonicValue = "--"; // 超声波值
        QString TEVValue = "--";        // 暂态地电压值

        QJsonObject blockObj = blockVal.toObject();
        QString blockId = blockObj["block_id"].toString();
        QString blockName = blockObj["block_name"].toString();
        QJsonArray params = blockObj["parameters"].toArray();

        QList<QPair<QString, DataBlock>> paramList;
        for (const QJsonValue &paramVal : params)
        {
            QJsonObject paramObj = paramVal.toObject();
            DataBlock info(paramObj); // 使用构造函数初始化

            // 根据类型识别柜内传感器
            if (info.position.contains("柜内"))
            {
                if (info.position.contains("温度") || info.type == "柜内温度")
                {
                    isHaveInTemp = true;
                    TempValue = info.data;
                }

                if (info.position.contains("湿度") || info.type == "柜内湿度")
                {
                    isHaveInHum = true;
                    HumValue = info.data;
                }
            }
            else if (info.type == "超声波")
            {
                isHaveInUltrasonic = true;
                UltrasonicValue = info.data;
            }
            else if (info.type == "暂态地电压")
            {
                isHaveInTEV = true;
                TEVValue = info.data;
            }
            else
            {
                paramList.append(qMakePair(info.identifier, info));
            }
        }

        // 将块和参数列表添加到主列表中
        m_dataBlockMap.append(qMakePair(blockName, paramList));
        m_dataBlockMap_isTempIn.insert(blockName, isHaveInTemp);
        m_dataBlockMap_isTempOut.insert(blockName, TempValue);
        m_dataBlockMap_isHumIn.insert(blockName, isHaveInHum);
        m_dataBlockMap_isHumOut.insert(blockName, HumValue);

        // 添加超声波和暂态地电压映射
        m_dataBlockMap_isUltrasonicIn.insert(blockName, isHaveInUltrasonic);
        m_dataBlockMap_isUltrasonicOut.insert(blockName, UltrasonicValue);
        m_dataBlockMap_isTEVIn.insert(blockName, isHaveInTEV);
        m_dataBlockMap_isTEVOut.insert(blockName, TEVValue);
    }
    updateDataMap(); // 更新块

    // 更新柜内温湿度和新增的传感器类型
    for (auto it = m_dataBlockMap_isTempIn.constBegin(); it != m_dataBlockMap_isTempIn.constEnd(); ++it)
    {
        QString blockName = it.key();
        bool hasInternalTemp = it.value();
        g_dataBlockManagers.value(blockName)->setTempInVisible(hasInternalTemp);
    }
    for (auto it = m_dataBlockMap_isTempOut.constBegin(); it != m_dataBlockMap_isTempOut.constEnd(); ++it)
    {
        QString blockName = it.key();
        QString internalTemp = it.value();
        g_dataBlockManagers.value(blockName)->setTempIn(internalTemp);
    }
    for (auto it = m_dataBlockMap_isHumIn.constBegin(); it != m_dataBlockMap_isHumIn.constEnd(); ++it)
    {
        QString blockName = it.key();
        bool hasInternalHum = it.value();
        g_dataBlockManagers.value(blockName)->setHumInVisible(hasInternalHum);
    }
    for (auto it = m_dataBlockMap_isHumOut.begin(); it != m_dataBlockMap_isHumOut.end(); ++it)
    {
        QString blockName = it.key();
        QString humOut = it.value();
        g_dataBlockManagers.value(blockName)->setHumIn(humOut);
    }

    // 更新柜内超声波和暂态地电压
    for (auto it = m_dataBlockMap_isUltrasonicIn.constBegin(); it != m_dataBlockMap_isUltrasonicIn.constEnd(); ++it)
    {
        QString blockName = it.key();
        bool hasInternalUltrasonic = it.value();
        g_dataBlockManagers.value(blockName)->setUltrasonicVisible(hasInternalUltrasonic);
    }

    for (auto it = m_dataBlockMap_isUltrasonicOut.constBegin(); it != m_dataBlockMap_isUltrasonicOut.constEnd(); ++it)
    {
        QString blockName = it.key();
        QString internalUltrasonic = it.value();
        g_dataBlockManagers.value(blockName)->setUltrasonicData(internalUltrasonic);
    }

    for (auto it = m_dataBlockMap_isTEVIn.constBegin(); it != m_dataBlockMap_isTEVIn.constEnd(); ++it)
    {
        QString blockName = it.key();
        bool hasInternalTEV = it.value();
        g_dataBlockManagers.value(blockName)->setTEVVisible(hasInternalTEV);
    }

    for (auto it = m_dataBlockMap_isTEVOut.constBegin(); it != m_dataBlockMap_isTEVOut.constEnd(); ++it)
    {
        QString blockName = it.key();
        QString internalTEV = it.value();
        g_dataBlockManagers.value(blockName)->setTEVData(internalTEV);
    }
}

/**
 * @brief plugin_datablock::updateDataMap 根据m_dataBlockMap刷新和创建ui
 */
void plugin_datablock::updateDataMap()
{
    bool isChanged = false;

    // 获取当前和之前的块名称集合（保持顺序）
    QList<QString> currentBlocks;
    for (const auto &pair : m_dataBlockMap)
    {
        currentBlocks.append(pair.first);
    }

    QList<QString> previousBlocks;
    for (const auto &pair : m_dataBlockMap_pre)
    {
        previousBlocks.append(pair.first);
    }

    // 处理新增的块（按顺序）
    for (const auto &currentPair : m_dataBlockMap)
    {
        QString blockName = currentPair.first;
        if (!previousBlocks.contains(blockName))
        {
            datablock_manager *manager = new datablock_manager();
            // 信号绑定
            QObject::connect(manager, &datablock_manager::signalToForward,
                             this, [this](const QString &arg)
                             { emit messageFromPlugin(pluginName(), arg); });
            manager->setBlockName(blockName);

            g_dataBlockManagers.insert(blockName, manager);
            qDebug() << "need to add bolck name: " << blockName << "size" << manager->size();

            // 取出参数信息,遍历这个列表,对所有信息进行新增（按顺序）
            QList<QPair<QString, DataBlock>> blockInfoList = currentPair.second;
            bool isHaveInTemp = false;       // 是否显示柜内温度
            bool isHaveInHum = false;        // 是否显示柜内湿度
            bool isHaveInUltrasonic = false; // 是否显示超声波
            bool isHaveInTEV = false;        // 是否显示暂态地电压

            for (const auto &paramPair : blockInfoList)
            {
                const QString &key = paramPair.first;          // 获取键,也就是identifier
                const DataBlock &dataBlock = paramPair.second; // 获取值

                if (manager->createBlock(dataBlock) == dataBlock.identifier.toInt())
                {
                    qDebug() << "add param " << dataBlock.identifier << " complete!";
                }
            }

            // 更新ui(根据g_dataBlockManagers按顺序全部重新排序放置)
            isChanged = true;
            // 在添加到 g_dataBlockManagers 之前设置阈值
            qDebug() << "========setTemperatureThreshold: " << m_temperatureThreshold;
            manager->setTemperatureThreshold(m_temperatureThreshold);
            manager->setHumidityThreshold(m_humidityThreshold);
            manager->setUltrasonicThreshold(m_ultrasonicThreshold);
            manager->setTEVThreshold(m_tevThreshold);
            manager->setHumInVisible(isHaveInHum);
            manager->setTempInVisible(isHaveInTemp);
            manager->setUltrasonicVisible(isHaveInUltrasonic);
            manager->setTEVVisible(isHaveInTEV);
        }
    }

    // 处理删除的块
    for (const auto &previousPair : m_dataBlockMap_pre)
    {
        QString blockName = previousPair.first;
        if (!currentBlocks.contains(blockName))
        {
            if (g_dataBlockManagers.contains(blockName))
            {
                datablock_manager *manager = g_dataBlockManagers.take(blockName);
                delete manager;
                qDebug() << "need to delete bolckName: " << blockName;
                // 更新ui
                isChanged = true;
            }
        }
    }

    // 处理现有块中的参数变化
    for (const auto &currentPair : m_dataBlockMap)
    {
        QString blockName = currentPair.first;
        if (previousBlocks.contains(blockName))
        {
            datablock_manager *manager = g_dataBlockManagers.value(blockName);
            if (!manager)
                continue;

            // 找到对应的旧数据
            QList<QPair<QString, DataBlock>> currentParams = currentPair.second;
            QList<QPair<QString, DataBlock>> previousParams;
            for (const auto &prevPair : m_dataBlockMap_pre)
            {
                if (prevPair.first == blockName)
                {
                    previousParams = prevPair.second;
                    break;
                }
            }

            // 提取键集合进行比较
            QSet<QString> currentIds;
            for (const auto &pair : currentParams)
            {
                currentIds.insert(pair.first);
            }

            QSet<QString> previousIds;
            for (const auto &pair : previousParams)
            {
                previousIds.insert(pair.first);
            }

            // 新增参数
            QSet<QString> addedParams = currentIds - previousIds;
            for (const QString &paramId : addedParams)
            {
                // 找到对应的DataBlock
                DataBlock dataBlock;
                for (const auto &pair : currentParams)
                {
                    if (pair.first == paramId)
                    {
                        dataBlock = pair.second;
                        break;
                    }
                }

                manager->createBlock(dataBlock);
                qDebug() << "新增参数:" << paramId;
                isChanged = true;
            }

            // 删除参数
            QSet<QString> removedParams = previousIds - currentIds;
            for (const QString &paramId : removedParams)
            {
                // 找到对应的DataBlock
                DataBlock dataBlock;
                for (const auto &pair : previousParams)
                {
                    if (pair.first == paramId)
                    {
                        dataBlock = pair.second;
                        break;
                    }
                }

                manager->deleteBlock(dataBlock.identifier.toInt());
                qDebug() << "删除参数:" << paramId;
                isChanged = true;
            }

            // 更新变化的参数
            QSet<QString> commonParams = previousIds & currentIds;
            for (const QString &paramId : commonParams)
            {
                // 找到对应的DataBlock
                DataBlock currentData;
                for (const auto &pair : currentParams)
                {
                    if (pair.first == paramId)
                    {
                        currentData = pair.second;
                        break;
                    }
                }

                DataBlock previousData;
                for (const auto &pair : previousParams)
                {
                    if (pair.first == paramId)
                    {
                        previousData = pair.second;
                        break;
                    }
                }

                if (!(currentData == previousData))
                {
                    manager->updateBlockData(currentData.identifier.toInt(), currentData);
                }
            }
        }
    }

    // 更新旧数据备份
    m_dataBlockMap_pre = m_dataBlockMap;
    if (isChanged)
    {
        updateLayout(); // 集体更新,刷新ui
    }
}

void plugin_datablock::updateLayout()
{
    // 清空布局，但保留布局本身
    QLayout *contentLayout = plugin_datablock_ui->scrollAreaWidgetContents->layout();
    while (QLayoutItem *child = contentLayout->takeAt(0))
    {
        delete child;
    }
    // 设置布局为靠上对齐
    if (auto vLayout = qobject_cast<QVBoxLayout *>(contentLayout))
    {
        vLayout->setAlignment(Qt::AlignTop);
    }

    // 按JSON顺序添加所有manager到布局中
    for (const auto &pair : m_dataBlockMap)
    {
        QString blockName = pair.first;
        datablock_manager *manager = g_dataBlockManagers.value(blockName);
        if (manager)
        {
            contentLayout->addWidget(manager);
        }
    }

    // 触发所有manager的内部布局更新（按JSON顺序）
    for (const auto &pair : m_dataBlockMap)
    {
        QString blockName = pair.first;
        datablock_manager *manager = g_dataBlockManagers.value(blockName);
        if (manager)
        {
            manager->updateLayout();
        }
    }

    // 只进行一次布局激活
    contentLayout->activate();
}

void plugin_datablock::setTemperatureThreshold(double threshold)
{
    m_temperatureThreshold = threshold;

    // 为所有已存在的 manager 设置阈值
    for (auto it = g_dataBlockManagers.constBegin(); it != g_dataBlockManagers.constEnd(); ++it)
    {
        it.value()->setTemperatureThreshold(threshold);
    }
}

void plugin_datablock::setInternalTemperatureThreshold(double threshold)
{
    m_internalTemperatureThreshold = threshold;

    // 注意：这里可能需要添加专门的内部温度阈值设置函数
    // 目前暂时使用普通温度阈值设置函数
    for (auto it = g_dataBlockManagers.constBegin(); it != g_dataBlockManagers.constEnd(); ++it)
    {
        it.value()->setTemperatureThreshold(threshold);
    }
}

void plugin_datablock::setHumidityThreshold(double threshold)
{
    m_humidityThreshold = threshold;

    // 为所有已存在的 manager 设置阈值
    for (auto it = g_dataBlockManagers.constBegin(); it != g_dataBlockManagers.constEnd(); ++it)
    {
        it.value()->setHumidityThreshold(threshold);
    }
}

void plugin_datablock::setUltrasonicThreshold(double threshold)
{
    m_ultrasonicThreshold = threshold;

    // 为所有已存在的 manager 设置阈值
    for (auto it = g_dataBlockManagers.constBegin(); it != g_dataBlockManagers.constEnd(); ++it)
    {
        it.value()->setUltrasonicThreshold(threshold);
    }
}

void plugin_datablock::setTEVThreshold(double threshold)
{
    m_tevThreshold = threshold;

    // 为所有已存在的 manager 设置阈值
    for (auto it = g_dataBlockManagers.constBegin(); it != g_dataBlockManagers.constEnd(); ++it)
    {
        it.value()->setTEVThreshold(threshold);
    }
}